﻿using System;
using System.Linq;
using System.Drawing;
using System.ComponentModel;
using System.Windows.Forms;
using LinqKit;
using Syncfusion.Drawing;
using Syncfusion.Windows.Forms;
using Syncfusion.Windows.Forms.Grid;
using Syncfusion.Windows.Forms.Grid.Grouping;
using Syncfusion.GridHelperClasses;
using Syncfusion.GridExcelConverter;
using Syncfusion.GroupingGridExcelConverter;
using Syncfusion.Pdf;
using Syncfusion.Pdf.Graphics;

using PMngr.Data;

namespace PMngr.Main
{
    public partial class SubReport : BaseControl
    {
        private IRepositoryFactory repositoryFactory;

        public SubReport()
        {
            InitializeComponent();
            // GridGroupingControl
            InitializeGridGrouping();
        }

        public SubReport(IRepositoryFactory repositoryFactory) : this()
        {
            this.repositoryFactory = repositoryFactory;
        }

        public override void InitializeControls()
        {
            // 单位区域
            InitializeDropDownList();
            // 主管部门
            InitializeComboBox(null);
        }

        #region Initialization
        private void InitializeDropDownList()
        {
            using (var repository = repositoryFactory.CreateRepository())
            {
                // 单位区域
                var options = repository.All<ItemBase>();
                var datasource1 = from o in options
                                  where o.Type == "UnitType" && o.IsValid
                                  orderby o.Order
                                  select new {Code = o.Code, Name = o.Name};
                var result = datasource1.ToList();
                result.Insert(0, new {Code = DefaultAll.DefaultValue, Name = DefaultAll.DefaultName});
                this.comUnitType.DataSource = result;
                this.comUnitType.DisplayMember = ItemModel.GetPropertyName(u => u.Name);
                this.comUnitType.ValueMember = ItemModel.GetPropertyName(u => u.Code);
            }
            
            this.comUnitType.SelectedIndexChanged += new System.EventHandler(this.comUnitType_SelectedIndexChanged);      
        }

        private void InitializeComboBox(int? unitType)
        {
            using (var repository = repositoryFactory.CreateRepository())
            {
                // 主管部门
                var units = repository.Find<Unit>(u => u.IsValid && u.ParentUnit == null);

                if (unitType.HasValue)
                {
                    units = units.Where(u => u.UnitType.Code == unitType.Value);
                }

                var datasource = from u in units
                                 select new {u.Id, u.Name, Subsidiary = u.ChildUnits.Count};

                var result = datasource.ToList();
                var quantity = result.Sum(r => r.Subsidiary);
                result.Insert(0,
                              new {Id = DefaultAll.DefaultValue, Name = DefaultAll.DefaultName, Subsidiary = quantity});
                comUnit.DataSource = result;
                comUnit.DisplayMember = UnitModel.GetPropertyName(u => u.Name);
                comUnit.ValueMember = UnitModel.GetPropertyName(u => u.Id);
            }
            // settings
            GridControl grid = comUnit.ListBox.Grid;
            grid.Cols.DefaultSize = 150;
            grid.HideCols[UnitModel.GetPropertyName(u => u.Id)] = true;
            grid.PrepareViewStyleInfo += GridListPrepareViewStyleInfo;
        }

        #region MultiColumnComboBox GridListControl Events
        private static void GridListPrepareViewStyleInfo(object sender, GridPrepareViewStyleInfoEventArgs e)
        {
            if (e.ColIndex == 2 && e.RowIndex == 0)
            {
                e.Style.Text = Utilities.MajorUnitSelected;
            }
            if (e.ColIndex == 3 && e.RowIndex == 0)
            {
                e.Style.Text = Utilities.UnitSelected;
            }            
        }
        #endregion

        #region GridGroupingControl
        private void InitializeGridGrouping()
        {
            GridColumnDescriptor gcd = new GridColumnDescriptor(UnitModel.GetPropertyName(u => u.Id), UnitModel.GetPropertyName(u => u.Id), UnitModel.Dict[UnitModel.GetPropertyName(u => u.Id)]);
            this.gridList.TableDescriptor.Columns.Add(gcd);
            GridColumnDescriptor gcd1 = new GridColumnDescriptor(UnitModel.GetPropertyName(u => u.Name), UnitModel.GetPropertyName(u => u.Name), UnitModel.Dict[UnitModel.GetPropertyName(u => u.Name)]);
            gcd1.Width = 250;
            this.gridList.TableDescriptor.Columns.Add(gcd1);
            GridColumnDescriptor gcd2 = new GridColumnDescriptor(UnitModel.GetPropertyName(u => u.UnitKind), UnitModel.GetPropertyName(u => u.UnitKind), UnitModel.Dict[UnitModel.GetPropertyName(u => u.UnitKind)], true, 100);
            this.gridList.TableDescriptor.Columns.Add(gcd2);
            GridColumnDescriptor gcd3 = new GridColumnDescriptor(UnitModel.GetPropertyName(u => u.Capacity), UnitModel.GetPropertyName(u => u.Capacity), UnitModel.Dict[UnitModel.GetPropertyName(u => u.Capacity)], true, 80);
            this.gridList.TableDescriptor.Columns.Add(gcd3);
            GridColumnDescriptor gcd4 = new GridColumnDescriptor(UnitModel.GetPropertyName(u => u.Contact), UnitModel.GetPropertyName(u => u.Contact), UnitModel.Dict[UnitModel.GetPropertyName(u => u.Contact)], true, 80);
            this.gridList.TableDescriptor.Columns.Add(gcd4);
            GridColumnDescriptor gcd5 = new GridColumnDescriptor(UnitModel.GetPropertyName(u => u.ContactTel), UnitModel.GetPropertyName(u => u.ContactTel), UnitModel.Dict[UnitModel.GetPropertyName(u => u.ContactTel)], true, 100);
            this.gridList.TableDescriptor.Columns.Add(gcd5);
            GridColumnDescriptor gcd6 = new GridColumnDescriptor(UnitModel.GetPropertyName(u => u.SuperUnit), UnitModel.GetPropertyName(u => u.SuperUnit), UnitModel.Dict[UnitModel.GetPropertyName(u => u.SuperUnit)], true, 150);
            this.gridList.TableDescriptor.Columns.Add(gcd6);
            GridColumnDescriptor gcd7 = new GridColumnDescriptor(UnitModel.GetPropertyName(u => u.Address), UnitModel.GetPropertyName(u => u.Address), UnitModel.Dict[UnitModel.GetPropertyName(u => u.Address)], true, 200);
            this.gridList.TableDescriptor.Columns.Add(gcd7);
            GridColumnDescriptor gcd8 = new GridColumnDescriptor(UnitModel.GetPropertyName(u => u.UnitType), UnitModel.GetPropertyName(u => u.UnitType), UnitModel.Dict[UnitModel.GetPropertyName(u => u.UnitType)], true, 80);
            this.gridList.TableDescriptor.Columns.Add(gcd8);
            GridColumnDescriptor gcd9 = new GridColumnDescriptor(UnitModel.GetPropertyName(u => u.CreateDate), UnitModel.GetPropertyName(u => u.CreateDate), UnitModel.Dict[UnitModel.GetPropertyName(u => u.CreateDate)], true, 140);
            this.gridList.TableDescriptor.Columns.Add(gcd9);
            // hide the trivial items
            this.gridList.TableDescriptor.VisibleColumns.Remove(UnitModel.GetPropertyName(u => u.Id));    

            this.gridList.TableDescriptor.Name = "单位";
            this.gridList.TableDescriptor.FrozenColumn = UnitModel.GetPropertyName(u => u.Name);

            gridList.InitializeGridGroupingWithFormat("[IsValid] LIKE 'false'");
            // caption
            this.gridList.TopLevelGroupOptions.ShowCaption = true;
            this.gridList.TopLevelGroupOptions.CaptionText = Utilities.CategoryCaption;
            // group drop
            this.gridList.ShowGroupDropArea = true;
            this.gridList.GridGroupDropArea.DragColumnHeaderText = Utilities.Grouping;

            this.gridList.DataSource = null;
        }
        #endregion

        #endregion

        private void btnSearch_Click(object sender, EventArgs e)
        {
            var unitType = (int)this.comUnitType.SelectedValue;
            var unit = DefaultAll.DefaultValue;
            if (this.comUnit.SelectedValue != null)
            {
                unit = (int)this.comUnit.SelectedValue;

                SetupGroupingControl(unitType, unit);
            }
            else
            {
                var unitName = this.comUnit.Text;
                SetupGroupingControl(unitType, unitName);
            }
        }

        private void SetupGroupingControl(int unitType, string unitName)
        {
            var predicate = PredicateBuilder.True<Unit>();
            predicate = predicate.And(u => u.ParentUnit != null);

            if (unitType != -1)
                predicate = predicate.And(u => u.ParentUnit.UnitType.Code == unitType);
            //
            predicate = predicate.And(u => u.ParentUnit.Name == unitName);

            using (var repository = repositoryFactory.CreateRepository())
            {
                var datasource = repository.Find<Unit>(predicate.Expand()).Select(u => new UnitModel
                                                                                           {
                                                                                               Id = u.Id,
                                                                                               Name = u.Name,
                                                                                               UnitKind =
                                                                                                   u.UnitType.Name,
                                                                                               Capacity = u.Capacity,
                                                                                               Contact = u.Contact,
                                                                                               ContactTel = u.ContactTel,
                                                                                               SuperUnit =
                                                                                                   u.ParentUnit.Name,
                                                                                               Address = u.Address,
                                                                                               UnitType =
                                                                                                   u.ParentUnit.UnitType
                                                                                                   .Name,
                                                                                               CreateDate = u.CreateDate,
                                                                                               IsValid = u.IsValid,
                                                                                               UnitTypeCode =
                                                                                                   u.UnitType.Code
                                                                                           });

                var result = datasource.ToList();
                this.gridList.DataSource = result;
            }
        }

        private void SetupGroupingControl(int unitType, int pId)
        {
            var predicate = PredicateBuilder.True<Unit>();
            predicate = predicate.And(u => u.ParentUnit != null);
            
            if(unitType != -1)
                predicate = predicate.And(u => u.ParentUnit.UnitType.Code == unitType); 
            //
            if (pId != -1)
                predicate = predicate.And(u => u.ParentUnit.Id == pId);

            using (var repository = repositoryFactory.CreateRepository())
            {
                var datasource = repository.Find<Unit>(predicate.Expand()).Select(u => new UnitModel
                                                                                           {
                                                                                               Id = u.Id,
                                                                                               Name = u.Name,
                                                                                               UnitKind =
                                                                                                   u.UnitType.Name,
                                                                                               Capacity = u.Capacity,
                                                                                               Contact = u.Contact,
                                                                                               ContactTel = u.ContactTel,
                                                                                               SuperUnit =
                                                                                                   u.ParentUnit.Name,
                                                                                               Address = u.Address,
                                                                                               UnitType =
                                                                                                   u.ParentUnit.UnitType
                                                                                                   .Name,
                                                                                               CreateDate = u.CreateDate,
                                                                                               IsValid = u.IsValid,
                                                                                               UnitTypeCode =
                                                                                                   u.UnitType.Code
                                                                                           });

                var result = datasource.ToList();
                foreach (var unit in result)
                {
                    if (unit.Address == null) unit.Address = String.Empty;
                    if (unit.Contact == null) unit.Contact = String.Empty;
                    if (unit.Description == null) unit.Description = String.Empty;
                    if (unit.UnitType == null) unit.UnitType = String.Empty;
                    if (unit.SuperUnit == null) unit.SuperUnit = String.Empty;
                }

                this.gridList.DataSource = result;
            }
        }

        private void comUnitType_SelectedIndexChanged(object sender, EventArgs e)
        {
            var unitType = this.comUnitType.SelectedValue;
            // 主管部门
            if ((int)unitType == -1)
            {
                InitializeComboBox(null);
            }
            else
            {               
                InitializeComboBox((int)unitType);
            }
        }          

        private void comUnit_KeyPress(object sender, KeyPressEventArgs e)
        {
            if (e.Handled == false)
            {
                if (this.comUnit.DroppedDown == false)
                {
                    this.comUnit.DroppedDown = true;
                }
            }
            else
            {
                this.comUnit.DroppedDown = false;
            }
        }

        #region 导出

        #region Excel
        private void ExcelToolStripMenuItem_Click(object sender, EventArgs e)
        {
            SaveFileDialog saveFileDialog = new SaveFileDialog();
            saveFileDialog.Filter = "Files(*.xls)|*.xls";
            saveFileDialog.FileName = String.Format("{0}.xls", DateTime.Now.ToString("yyyyMMddhhmmss"));
            saveFileDialog.AddExtension = true;
            saveFileDialog.DefaultExt = ".xls";

            if (saveFileDialog.ShowDialog() == DialogResult.OK && saveFileDialog.CheckPathExists)
            {
                gridList.ExportToExcel(saveFileDialog.FileName);

                if (MessageFactory.MessageBoxShow(Utilities.OpenExcelConfirmed) == DialogResult.Yes)
                {
                    System.Diagnostics.Process proc = new System.Diagnostics.Process();
                    proc.StartInfo.FileName = saveFileDialog.FileName;
                    proc.Start();
                }
            }
        }
        #endregion

        #region Pdf
        private void PdfToolStripMenuItem_Click(object sender, EventArgs e)
        {
            SaveFileDialog saveFileDialog = new SaveFileDialog();
            saveFileDialog.Filter = "Files(*.pdf)|*.pdf";
            saveFileDialog.AddExtension = true;
            saveFileDialog.DefaultExt = ".pdf";

            if (saveFileDialog.ShowDialog() == DialogResult.OK && saveFileDialog.CheckPathExists)
            {
                GridPDFConverter pdfConvertor = new GridPDFConverter();

                pdfConvertor.ShowHeader = true;
                pdfConvertor.ShowFooter = true;

                pdfConvertor.Margins.Left = 1f;
                pdfConvertor.Margins.Right = 1f;
                pdfConvertor.Margins.Top = 1f;
                pdfConvertor.Margins.Bottom = 1f;

                //pdfConvertor.DrawPDFHeader += new GridPDFConverter.DrawPDFHeaderFooterEventHandler(pdfConvertor_DrawPDFHeader);

                //pdfConvertor.DrawPDFFooter += new GridPDFConverter.DrawPDFHeaderFooterEventHandler(pdfConvertor_DrawPDFFooter);

                pdfConvertor.Margins.All = 25;
                pdfConvertor.ExportToPdf(saveFileDialog.FileName, this.gridList.TableControl);
                //Launching the PDF file using the default Application.[Acrobat Reader]
                if (MessageFactory.MessageBoxShow(Utilities.OpenPdfConfirmed) == DialogResult.Yes)
                {
                    System.Diagnostics.Process proc = new System.Diagnostics.Process();
                    proc.StartInfo.FileName = saveFileDialog.FileName;
                    proc.Start();
                }
            }
        }

        void pdfConvertor_DrawPDFFooter(object sender, PDFHeaderFooterEventArgs e)
        {

            PdfPageTemplateElement footer = e.HeaderFooterTemplate;

            PdfFont font = new PdfStandardFont(PdfFontFamily.Helvetica, 8);

            PdfSolidBrush brush = new PdfSolidBrush(Color.Gray);

            PdfPen pen = new PdfPen(Color.DarkBlue, 3f);
            font = new PdfStandardFont(PdfFontFamily.Helvetica, 6, PdfFontStyle.Bold);
            PdfStringFormat format = new PdfStringFormat();
            format.Alignment = PdfTextAlignment.Center;
            format.LineAlignment = PdfVerticalAlignment.Middle;
            footer.Graphics.DrawString("@Copyright 2011", font, brush, new RectangleF(0, footer.Height - 40, footer.Width, footer.Height), format);

            format = new PdfStringFormat();
            format.Alignment = PdfTextAlignment.Right;
            format.LineAlignment = PdfVerticalAlignment.Bottom;

            //Create page number field
            PdfPageNumberField pageNumber = new PdfPageNumberField(font, brush);

            //Create page count field
            PdfPageCountField count = new PdfPageCountField(font, brush);

            PdfCompositeField compositeField = new PdfCompositeField(font, brush, "Page {0} of {1}", pageNumber, count);
            compositeField.Bounds = footer.Bounds;
            compositeField.Draw(footer.Graphics, new PointF(470, footer.Height - 10));
        }

        void pdfConvertor_DrawPDFHeader(object sender, PDFHeaderFooterEventArgs e)
        {
            PdfPageTemplateElement header = e.HeaderFooterTemplate;

            PdfFont font = new PdfStandardFont(PdfFontFamily.Helvetica, 24);
            float doubleHeight = font.Height * 2;
            Color activeColor = Color.FromArgb(44, 71, 120);
            SizeF imageSize = new SizeF(110f, 35f);
            //Locating the logo on the right corner of the Drawing Surface
            PointF imageLocation = new PointF(e.HeaderFooterTemplate.Width - imageSize.Width - 20, 5);

            PdfImage img = new PdfBitmap(@".\logo.png");

            //Draw the image in the Header.
            header.Graphics.DrawImage(img, imageLocation, imageSize);

            PdfSolidBrush brush = new PdfSolidBrush(activeColor);

            PdfPen pen = new PdfPen(Color.DarkBlue, 3f);
            font = new PdfStandardFont(PdfFontFamily.Helvetica, 16, PdfFontStyle.Bold);

            //Set formattings for the text
            PdfStringFormat format = new PdfStringFormat();
            format.Alignment = PdfTextAlignment.Center;
            format.LineAlignment = PdfVerticalAlignment.Middle;


            //Draw title
            header.Graphics.DrawString("Syncfusion Essential Grid", font, brush, new RectangleF(0, 0, header.Width, header.Height), format);
            brush = new PdfSolidBrush(Color.Gray);
            font = new PdfStandardFont(PdfFontFamily.Helvetica, 6, PdfFontStyle.Bold);

            format = new PdfStringFormat();
            format.Alignment = PdfTextAlignment.Left;
            format.LineAlignment = PdfVerticalAlignment.Bottom;

            //Draw some lines in the header
            pen = new PdfPen(Color.DarkBlue, 0.7f);
            header.Graphics.DrawLine(pen, 0, 0, header.Width, 0);
            pen = new PdfPen(Color.DarkBlue, 2f);
            header.Graphics.DrawLine(pen, 0, 03, header.Width + 3, 03);
            pen = new PdfPen(Color.DarkBlue, 2f);
            header.Graphics.DrawLine(pen, 0, header.Height - 3, header.Width, header.Height - 3);
            header.Graphics.DrawLine(pen, 0, header.Height, header.Width, header.Height);
        }
        #endregion        

        #endregion

    }
}
